package org.jiuling.spring.unifyinfo.exception.handing;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import org.jiuling.local.tools.exception.LocalToolsRuntimeException;
import org.jiuling.network.tools.response.ResponseData;
import org.jiuling.network.tools.response.enums.ResponseCodeEnum;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Set;
import java.util.stream.Collectors;

/**
 * 统一异常处理
 * @author 紫灵
 * @date 2022年10月09日 15时13分08秒
 */
@RestControllerAdvice
public class UnifiedExceptionHandling {

    @ResponseBody
    @ExceptionHandler(BindException.class)
    public ResponseData<?> bindExceptionIntercept(BindException e){
        return new ResponseData<>(ResponseCodeEnum.ERROR,e.getBindingResult().getAllErrors().parallelStream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining("、")));
    }

    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseData<?> methodArgumentNotValidExceptionIntercept(MethodArgumentNotValidException e){
        return new ResponseData<>(ResponseCodeEnum.ERROR,e.getBindingResult().getAllErrors().parallelStream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining("、")));
    }


    /**
     * 本地工具异常拦截
     * @param e 本地工具异常
     * @return 异常处理结果
     */
    @ResponseBody
    @ExceptionHandler(LocalToolsRuntimeException.class)
    public ResponseData<?> LocalToolsRuntimeExceptionIntercept(LocalToolsRuntimeException e){
        return new ResponseData<>(ResponseCodeEnum.ERROR,e.getLocalizedMessage());
    }

    /**
     * Http请求方法不支持异常拦截
     * @param e Http请求方法不支持异常
     * @return 异常处理结果
     */
    @ResponseBody
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ResponseData<?> httpRequestMethodNotSupportedExceptionIntercept(HttpRequestMethodNotSupportedException e){
        return new ResponseData<>(ResponseCodeEnum.METHODS_ERROR,"该接口不支持 "+e.getMethod()+" 请使用 "+e.getSupportedHttpMethods()+ " 方法");
    }

    /**
     * 约束违反例外拦截
     * @param e 约束违反例外
     * @return 异常处理结果
     */
    @ResponseBody
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseData<?> constraintViolationExceptionIntercept(ConstraintViolationException e){
        StringBuilder stringBuilder = new StringBuilder();
        Set<ConstraintViolation<?>> constraintViolationSet = e.getConstraintViolations();
        constraintViolationSet.forEach(constraintViolation -> {
            stringBuilder.append(constraintViolation.getMessage());
            stringBuilder.append("、");
        });
        stringBuilder.deleteCharAt(stringBuilder.length()-1);
        String msg = stringBuilder.toString()
                .replaceAll("！", "")
                .replaceAll("!","")
                +"！";
        return new ResponseData<>(ResponseCodeEnum.ERROR,msg);
    }

    /**
     * 运行时异常拦截
     * @param e 运行时异常
     * @return 异常处理结果
     */
    @ResponseBody
    @ExceptionHandler(RuntimeException.class)
    public ResponseData<?> runtimeExceptionIntercept(RuntimeException e){
        e.printStackTrace();
        return new ResponseData<>(ResponseCodeEnum.EXCEPTION,"异常操作！");
    }

    @ResponseBody
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseData<?> httpMessageNotReadableExceptionIntercept(HttpMessageNotReadableException e){
        return new ResponseData<>(ResponseCodeEnum.EXCEPTION,e.getLocalizedMessage());
    }

    /**
     * 异常拦截
     * @param e 异常
     * @return 异常处理结果
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public ResponseData<?> exceptionIntercept(Exception e){
        e.printStackTrace();
        return new ResponseData<>(ResponseCodeEnum.EXCEPTION,"异常操作！");
    }



}
